import 'dart:async';
import 'dart:io';

import 'package:fixnum/src/int64.dart';
import 'package:flutter/material.dart';
import 'package:tiktokadult/hj_page/zaixiankefu/chat_widget/chat_page/List_component/ListComponentPage.dart';
import 'package:tiktokadult/hj_page/zaixiankefu/chat_widget/chat_page/utils/tool.dart';
import 'package:tiktokadult/hj_page/zaixiankefu/chat_widget/chat_page/utils/util.dart';
import 'package:tiktokadult/tools_base/appbar/custom_appbar.dart';

import '../chat_core/network/connection/connect_util.dart';
import '../chat_core/network/connection/dio_manager.dart';
import '../chat_core/network/connection/download_manager.dart';
import '../chat_core/network/connection/msg_manager.dart';
import '../chat_core/network/connection/socket_manager.dart';
import '../chat_core/network/utils/file_manager.dart';
import '../chat_core/pkt/pb.pb.dart';
import '../chat_model/chatFaqModel.dart';
import '../chat_model/chat_faq_model.dart';
import '../chat_model/userModel.dart';
import '../utils/logger.dart';
import 'bullet_box/bulletBox.dart';
import 'key_board_component/KeyBoardComponentPage.dart';

class ChatPage extends StatefulWidget {
  ChatPage(
    KefuUserModel model, {
    Key? key,
    required this.appId,
    this.waitCount,
  }) : super(key: key);

  KefuUserModel? kefuUserModel;
  PlayerInfo? playerInfo;

  //前端传过来的数据 重新定义PlayerInfo来接收
  PlayerInfo? forcePlayerInfo;

  // 客服信息
  ServicerInfoFields? servicerInfoFields;

  //展示faq数据的时候 需要配置顶部时间展示 定义为ServicerInfoFields类型
  ServicerInfoFields? timeServicerInfoFields;

  //是否禁言
  FreezePlayer? freezePlayer;

  // 消息内容
  String? text;

  // 返回信息
  ChatFields? chatFields;

  // 消息列表
  List<dynamic> list = [];

  // 客服断开信息
  EnterStatus? enterStatus;

  // 对方正在输入消息
  String? typing;

  // 是否是匿名用户
  String? anonymous;

  //是否需要滑动到底部
  bool isScrollToBottom = true;

//是否禁言 未禁言状态：false 禁言状态：true
  bool isNoTalk = false;

  //记录当前的session_id
  String currentSessionId = '';

  //是否需要显示或隐藏底部输入框   false不隐藏  true隐藏
  bool isNeedKeyboard = true;

  //下面的字段是webSocket未连接的时候  由上一个页面传递下来的
  //用户名
  String username = '';

  //用户头像
  String userAvatar = '';

  //客服头像
  String customerAvatar = '';

  //客服名字
  String customername = '';

  //用户的appId
  String appId = '';

  List<String> picList = [];

  // 对应子组件本地图片加载
  Map<String, bool> loadingState = {};

  // 图片上传
  Map<String, File>? images = {};

  //faq数据
  FaqModel? faqModel;

  //faq问题集
  QuestBean? questBean;

  //questype 当前记录的问题
  int questType = 0;

  //当前可用域名
  String? baseUrl;

  //是否已经连接webSocket
  // bool isConnect = false;
  //ListView是否倒置  默认不倒置
  bool reverse = false;

  //隐藏悬乎按钮
  bool offstage = true;

  bool isVoice = false;

  ///是否隐藏音频录制是的UI
  bool isHideRecord = true;

  ///当前语音录制状态的内容
  String? voiceContent;

  TextEditingController editController = TextEditingController();

  Map sendMsgStatus = {};
  List sendTimer = [];
  int? waitCount;

  @override
  State<ChatPage> createState() => ChatPageState();
}

class ChatPageState extends State<ChatPage> {
// 清空正在输入
  dynamic _typingTimer;

  ChatAnwserModel? chatAnwserModel;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
      child: Theme(
        data: SocketManager().model?.themeData ?? ThemeData(),
        child: Scaffold(
          backgroundColor: Color(0xfff8f8f8),
          appBar: CustomAppbar(
            title: "在线客服",
            actions: [
              GestureDetector(
                onTap: () {
                  //Get.to(SellerReportPage(parameters: {},));
                },
                child: const Text(
                  "举报",
                  style: TextStyle(color: Color(0xff999999), fontSize: 14),
                ),
              )
            ],
          ),
          body: SafeArea(
              child: Stack(
            children: <Widget>[
              Column(children: <Widget>[
                ListComponentPage(
                  list: widget.list,
                  key: globalListComponentPageStateKey,
                  playerInfo: widget.playerInfo,
                  keyBoardComponentPageState: keyBoardComponentPageStateKey,
                  sendMsgStatus: widget.sendMsgStatus,
                  sendTimer: widget.sendTimer,
                  forcePlayerInfo: widget.forcePlayerInfo,
                  chatFields: widget.chatFields,
                  servicerInfoFields: widget.servicerInfoFields,
                  timeServicerInfoFields: widget.timeServicerInfoFields,
                  isScrollToBottom: widget.isScrollToBottom,
                  images: widget.images!,
                  currentSessionId: widget.currentSessionId,
                  customerAvatar: widget.customerAvatar,
                  customername: widget.customername,
                  userAvatar: widget.userAvatar,
                  username: widget.username,
                  isNeedKeyboard: widget.isNeedKeyboard,
                  loadingState: widget.loadingState,
                  questBean: widget.questBean,
                  faqModel: widget.faqModel,
                  questType: widget.questType,
                  reverse: widget.reverse,
                  //currentQuestion: widget.cu,
                  chatAnwserModel: chatAnwserModel,
                ),
                Container(height: 10),
                KeyBoardComponentPage(
                  key: keyBoardComponentPageStateKey,
                  listComponentPageState: globalListComponentPageStateKey,
                  appId: widget.appId,
                  playerInfo: widget.playerInfo,
                  servicerInfoFields: widget.servicerInfoFields,
                  chatFields: widget.chatFields,
                  enterStatus: widget.enterStatus,
                  images: widget.images,
                  freezePlayer: widget.freezePlayer,
                  faqModel: widget.faqModel,
                  list: widget.list,
                  text: widget.text,
                )

                /*widget.isNeedKeyboard == false
                    ? KeyBoardComponentPage(
                        key: keyBoardComponentPageStateKey,
                        listComponentPageState: globalListComponentPageStateKey,
                        appId: widget.appId,
                        playerInfo: widget.playerInfo,
                  servicerInfoFields: widget.servicerInfoFields,
                  chatFields: widget.chatFields,
                  enterStatus: widget.enterStatus,
                  images: widget.images,
                  freezePlayer: widget.freezePlayer,
                  faqModel: widget.faqModel,
                  list: widget.list,
                  text: widget.text,
                      )
                    : Container(),*/
              ]),
            ],
          )),
        ),
      ),
    );
  }

  GlobalKey<ListComponentPageState> globalListComponentPageStateKey = GlobalKey();
  GlobalKey<KeyBoardComponentPageState> keyBoardComponentPageStateKey = GlobalKey<KeyBoardComponentPageState>();

  @override
  void initState() {
    super.initState();
    _init();
  }

  void _sendMsgToRequestHistoryData() async {
    HistoryMessage historyMessage = HistoryMessage.create();
    historyMessage.id = await obtainValueByKey('id') == null ? "" : obtainValueByKey('id').toString();
    historyMessage.platId = await obtainValueByKey('platId') == null ? "" : obtainValueByKey('platId').toString();
    historyMessage.currentSessionId = await obtainValueByKey('sessionId') == null ? "" : obtainValueByKey('sessionId').toString();
    BaseMessage baseMessage = BaseMessage.create();
    baseMessage.action = 1008;
    baseMessage.data = historyMessage.writeToBuffer();

    MsgUtils.sendMessage(baseMessage.writeToBuffer());
    globalListComponentPageStateKey.currentState?.onChangeIsScrollToBottom(true);
    globalListComponentPageStateKey.currentState?.onChangeReverse(true);

    setState(() {});
  }

//获取faq数据 提取faq分类数据
  void dealFaqClassData(dynamic data) {
    ChatFaqModel faqModel = data;
    //初始化显示faq数据之前 需要展示当前时间
    ServicerInfoFields servicerInfoFields = ServicerInfoFields.create()..declaration = currentTime();
    //展示当前时间
    globalListComponentPageStateKey.currentState?.onShowCurrentTime(servicerInfoFields);
    //展示faq问题组件
    globalListComponentPageStateKey.currentState?.onShowChatFields(faqModel);

    //展示faq数据的时候  需要隐藏底部输入框  等连接websocket成功后再显示
    onChangeKeyBoard(true);

    setState(() {});
  }

  // 页面初始化
  void _init() async {
    Instance.isCallBack = true;
    //初始化的时候将未读消息数设置为0
    Instance.count = 0;
    SocketManager().getMsg!(0);
    var appId = widget.appId;
    Map<String, dynamic> map = Map();
    map['appId'] = appId; //测试appid == 456789
    //初始化获取faq数据
    if (Instance.isConnect == true) {
      // _onConnect(action, ctx);
      //连接成功之后  设置输入框不隐藏
      onChangeKeyBoard(false);
      globalListComponentPageStateKey.currentState?.onChangeReverse(true);

      setState(() {});

      if (Instance.isShut == true) {
        onConnect();
        MsgUtils.sendMsgToRequestLastTimeData();
        return;
      }
      if (Instance.isAnonymous == true) {
        onConnect();
      } else {
        MsgUtils.sendMsgToRequestLastTimeData();
        Future.delayed(Duration(milliseconds: 500), () {
          _sendMsgToRequestHistoryData();
        });
      }
      return;
    }
    if ((SocketManager().model?.faqApi?.length ?? 0) > 0 && Instance.isConnect == false) {
      DioUtils.requestHttp<Map<String, dynamic>>(SocketManager().model!.faqApi!, parameters: map, method: DioUtils.POST, onSuccess: (data) {
        print('======data===$data');
        try {
          ChatFaqModel model = ChatFaqModel.fromMap(data)!;
          if (model.data != null && (model.data?.length ?? 0) > 0) {
            //设置listView是否倒置 false不倒置 从上往下排列
            globalListComponentPageStateKey.currentState?.onChangeReverse(false);
            Instance.faqModel = model;
            dealFaqClassData(model);

            setState(() {});
          } else {
            //如果数据没有返回就直接连接WebSocket
            onConnect();
          }
        } catch (e) {
          onConnect();
        }
      }, onError: (error) {
        // print('=====error=======$error');
        //如果faq数据获取失败  直接连接webSocket
        onConnect();
      });
    } else {
      onConnect();
    }
  }

  void onSelectFaqItem(ChatDataBean bean) {
    globalListComponentPageStateKey.currentState?.oSendNoti();
    globalListComponentPageStateKey.currentState?.onChangeIsScrollToBottom(true);

    if (Instance.isConnect == false) {
      dealSendFaqMsgData(widget.text!, widget.username, widget.userAvatar, widget.playerInfo);
      loadAnwserDataByHttp(bean, widget.appId);
    } else {
      //链接成功之后  faq自动回复关闭 将问题直接以消息形式发送给服务器
      Map<String, dynamic> map = Map();
      map['text'] = bean.questName;
      GlobalKey<KeyBoardComponentPageState> keyBoardComponentPageState = GlobalKey();
      keyBoardComponentPageState.currentState?.onSendMsg(map);
    }

    setState(() {});
  }

  //处理faq用户数据 用来展示
  void dealSendFaqMsgData(String text, String username, String userAvatar, PlayerInfo? forcePlayerInfo) {
    //如果连接的是faq数据 当前是没有连接websocket 所以需要自己手动设定用户的名字和头像相关信息
    var playerInfo = PlayerInfo.create()
      ..username = username
      ..avatar = userAvatar ?? '';
    widget.forcePlayerInfo = playerInfo;
    setState(() {});
    //将用户选择的faq相关问题 拼接成ChatFields类型 用来统一展示
    int nowTime = DateTime.now().millisecondsSinceEpoch;
    ChatFields chatFields = ChatFields.create()
      ..username = username
      ..type = 1
      ..isRead = 2
      ..text = text
      ..time = Int64(nowTime) as Int64;
    globalListComponentPageStateKey.currentState?.onShowChatFields(chatFields);

    setState(() {});
  }

  //请求问题分类下面对应的答案
  void loadAnwserDataByHttp(ChatDataBean bean, String appId) async {
    var appId = widget.appId;
    Map<String, dynamic> map = Map();
    map['appId'] = appId;
    map['questType'] = bean.questType;
    DioUtils.requestHttp<Map<String, dynamic>>(
      (SocketManager().model!.faqApi) ?? "",
      parameters: map,
      method: DioUtils.POST,
      onSuccess: (data) {
        chatAnwserModel = ChatAnwserModel.fromMap(data)!;
        globalListComponentPageStateKey.currentState?.onShowChatFields(chatAnwserModel);

        setState(() {});
      },
      onError: (e) {
        onConnect();
      },
    );
  }

  void _listenMessageData(dynamic action, dynamic data) async {
    PrintUtil().log("action:$action\n---------------------\n$data");
    if (action == 2002) {
      widget.isNeedKeyboard = false;
      setState(() {});
    }

    if (action == 2009) {
      showSimpleDialog(context, data);
      widget.isNeedKeyboard = true;
      setState(() {});
    }

    if (action == 2012) {
      _typingTimer?.cancel();
      _typingTimer = null;
      _typingTimer = Timer(const Duration(milliseconds: 1500), () => widget.typing = null);
      setState(() {});
    }
    // var actio = selectAction(action, data);
    // if (actio != null) _ctx.dispatch(actio);
    switch (action) {
      case 2013:
        onPlayerInfo(data);
        break;
      case 2002:
        onServicerInfoFields(data);
        break;
      case 2005:
        chatUserInfo(data);
        break;
      case 2012:
        onTyping();
        break;
      case 2004:
        onGetVoice(data);
        break;
      case 2018:
        aswer(data);
        break;
      case 2003:
        if (globalListComponentPageStateKey != null) {
          globalListComponentPageStateKey.currentState?.onShow(data);
        }
        break;
      case 1010:
        if (keyBoardComponentPageStateKey != null) {
          keyBoardComponentPageStateKey.currentState?.onDontTalk(data);
        }
        break;
      case 2009:
        if (keyBoardComponentPageStateKey != null) {
          keyBoardComponentPageStateKey.currentState?.onEnterStatus(data);
        }
        break;
      case 2008:
        if (globalListComponentPageStateKey != null) {
          globalListComponentPageStateKey.currentState?.onGetHistory(data);
        }
        break;
      case 2010:
        if (globalListComponentPageStateKey != null) {
          globalListComponentPageStateKey.currentState?.onWait(data);
        }
        break;
      case 2000:
        if (globalListComponentPageStateKey != null) {
          globalListComponentPageStateKey.currentState?.onRefuse(data);
        }
        break;
      case 2006:
        if (globalListComponentPageStateKey != null) {
          globalListComponentPageStateKey.currentState?.onMsgRead();
        }
        break;
      default:
        break;
    }
    if (action == 2003 || action == 2004) _sendAswer(data);
    setState(() {});
  }

  // 发送应答
  void _sendAswer(data) {
    String sessionId = data.sessionId ?? "";
    String messageId = data.messageId ?? "";
    String targetId = data.targetId ?? "";
    String senderId = data.senderId ?? "";
    AckReplyPacket ackReplyPacket = AckReplyPacket.create()
      ..senderId = senderId
      ..sessionId = sessionId
      ..targetId = targetId
      ..messageId = messageId;

    BaseMessage baseMessage = BaseMessage.create();
    baseMessage.action = 1018;
    baseMessage.data = ackReplyPacket.writeToBuffer();
    PrintUtil().log("发送消息:1018");
    MsgUtils.sendMessage(baseMessage.writeToBuffer());
  }

  //选取问题对应的答案
  void onAnwser(Map<String, dynamic> map) {
    //发送通知 取消当前定时器读秒 -> 这个定时器是用户不小心点了已解决按钮
    //有一个10s的倒计时自动退出页面 但是用户如果又操作了其他功能 就取消
    globalListComponentPageStateKey.currentState?.oSendNoti();
    globalListComponentPageStateKey.currentState?.onChangeIsScrollToBottom(true);
    ChatResultModel? resultModel = ChatResultModel.fromMap(map);
    if (Instance.isConnect == false) {
      dealSendFaqMsgData(widget.text!, widget.username, widget.userAvatar, widget.playerInfo);
      //未链接webSocket的时候 才走faq流程
      Future.delayed(Duration(seconds: 1), () {
        globalListComponentPageStateKey.currentState!.onShowChatFields(resultModel);
      });
    } else {
      Map<String, dynamic> map = Map();
      map['text'] = resultModel?.questTitle ?? '';
      GlobalKey<KeyBoardComponentPageState> keyBoardComponentPageState = new GlobalKey();
      keyBoardComponentPageState.currentState?.onSendMsg(map);
    }

    setState(() {});
  }

  // 链接成功之后将faq数据颠倒顺序
  onconnectDeal() {
    List<dynamic> list = [];
    if (widget.list.length > 0) {
      for (var i = 0; i < widget.list.length; i++) {
        dynamic data = widget.list[i];
        list.insert(0, data);
      }
    }
    widget.list = list;
    setState(() {});
  }

  //点击未解决  执行socket连接
  void connectWeb(String string) async {
    //发送通知 取消当前定时器读秒 -> 这个定时器是用户不小心点了已解决按钮
    //有一个10s的倒计时自动退出页面 但是用户如果又操作了其他功能 就取消
    globalListComponentPageStateKey.currentState?.oSendNoti();
    //链接成功之后 把faq数据顺序颠倒
    onconnectDeal();
    if (widget.isScrollToBottom == false) {
      globalListComponentPageStateKey.currentState?.onChangeIsScrollToBottom(true);
      globalListComponentPageStateKey.currentState?.onChangeReverse(true);

      setState(() {});
    }
    int nowTime = DateTime.now().millisecondsSinceEpoch;
    ChatFields chatFields = ChatFields.create()
      ..sessionId = await obtainValueByKey('sessionId').toString()
      ..text = string ?? ''
      ..time = Int64(nowTime)
      ..username = (await obtainValueByKey('username') == null) ? widget.username : obtainValueByKey('username').toString()
      ..targetId = (await obtainValueByKey('servicerId') == null) ? "" : await obtainValueByKey('servicerId').toString()
      ..type = 1
      ..isRead = 2
      ..senderId = (await obtainValueByKey('id') == null) ? "" : await obtainValueByKey('id').toString();
    globalListComponentPageStateKey.currentState?.onShowChatFields(chatFields);
    Future.delayed(Duration(seconds: 1), () {
      onConnect();
    });

    setState(() {});
  }

  onChangeKeyBoard(bool isNeedKeyboard) {
    widget.isNeedKeyboard = isNeedKeyboard;
    setState(() {});
  }

  //连接webSocket
  void onConnect() async {
    globalListComponentPageStateKey.currentState?.onChangeReverse(true);
    String connectUrl = SocketManager().connectUrl;
    bool anonymous = Instance.isAnonymous;
    Object id = await obtainValueByKey('id') ?? '';
    var url = anonymous != true ? connectUrl : connectUrl + '&userId=$id';
    if (connectUrl != null) {
      await MsgUtils.longConnection(url, _listenMessageData);
    }

    Instance.isConnect = true;
    //连接成功之后  设置输入框隐藏
    onChangeKeyBoard(true);
    //第一次连接websocket 让用户主动去拉取历史记录 不做自动拉取 暂时注释掉
    Future.delayed(const Duration(milliseconds: 500), () {
      globalListComponentPageStateKey.currentState?.onSendReques();

      setState(() {});
    });

    setState(() {});
  }

  onPlayerInfo(dynamic data) {
    widget.playerInfo = data;
    setState(() {});
  }

  onServicerInfoFields(dynamic data) {
    ServicerInfoFields servicerInfoFields = data;
    ChatFields chatFields = ChatFields.create();
    chatFields.text = servicerInfoFields.declaration;
    widget.servicerInfoFields = servicerInfoFields;
    widget.list.insert(0, chatFields);
    widget.currentSessionId = servicerInfoFields.sessionId;
    Instance.customerAvatar = servicerInfoFields.avatar;
    Instance.customerUsername = servicerInfoFields.username;
    setState(() {});
  }

  ///下载语音 ///先判断是否是语音数据  再判断本地是否存在当前音频数据  有就不下载  没有就下载
  void downloadVoice(dynamic data) async {
    ChatFields chatFields = data;
    if (chatFields.photo != null && chatFields.photo.length > 0) {
      if (chatFields.photo.first.startsWith('aac')) {
        String path = await Network().isExist(chatFields);
        if (path.length == 0) {
          download(chatFields);
        }
      }
    }
  }

  void download(ChatFields chatFields) async {
    List l = chatFields.photo.first.split('_');
    var filename = "";
    for (var i = 0; i < l.length - 1; i++) {
      if (i == 0) {
        filename = l[0];
      } else {
        filename = filename + '_' + l[i];
      }
    }
    var localPath = await fileMgr.getRootPath() + '/' + filename + '.aac';
    String uri = SocketManager().model!.baseUrl! + '/audio/' + filename;
    try {
      Network().download(uri, localPath, (data) => {}, (e) => {});
    } catch (e) {
      print(e.toString());
    }
  }

  void chatUserInfo(dynamic data) {
    List list = data;
    var msgs = list.length > 0 ? list[0].msgs : [];
    print('===msgs====$msgs');
    for (var i = 0; i < msgs.length; i++) {
      ChatFields chatFields = msgs[i];
      Future.delayed(Duration(milliseconds: 500), () {
        downloadVoice(chatFields);
      });
    }
    onShow2005Data(data);
  }

  onShow2005Data(dynamic data) {
    List list = data;
    var msgs = list.length > 0 ? list[0].msgs : [];
    List l = [];
    for (var i = 0; i < msgs.length; i++) {
      var d = msgs[i];
      if (widget.reverse == false) {
        l.add(d);
      } else {
        l.insert(0, d);
      }
    }
    widget.list.addAll(l);
    setState(() {});
  }

  // 对方正在输入
  onTyping() {
    widget.typing = '对方正在输入...';
    setState(() {});
  }

  void onGetVoice(dynamic data) {
    /*
  chatAudio
  int64 time = 1; // 消息发送时间
    string text = 2; // 消息内容
    string audio = 3; // 语音地址
    string targetId = 4; // 接受人ID
    string senderId = 5; // 发送者ID
    string messageId = 6; // 消息ID（接收）0
    int32 isRead = 7; // 是否已读（接收）
    string username = 8; // 发送者昵称
    string sessionId = 9; // 会话ID
    int32 type = 10; // 发送人类型
    int64 duration = 11; // 消息时长
  */
    ChatAudio chatAudio = data;
    var audio = chatAudio.audio + '_' + chatAudio.duration.toString();
    ChatFields chatFields = ChatFields.create();
    chatFields.photo.add(audio ?? '');
    chatFields.time = chatAudio.time;
    chatFields.targetId = chatAudio.targetId;
    chatFields.senderId = chatAudio.senderId;
    chatFields.sessionId = chatAudio.sessionId;
    chatFields.text = chatAudio.text;
    chatFields.messageId = chatAudio.messageId;
    chatFields.username = chatAudio.username;
    chatFields.type = chatAudio.type;

    downloadVoice(chatFields);
    globalListComponentPageStateKey.currentState?.onShowChatFields(chatFields);

    setState(() {});
  }

  // 确认收到信息
  void aswer(dynamic data) {
    AckReplyPacket payload = data;
    String messageId = payload.messageId ?? "";
    widget.sendMsgStatus[messageId] = 3;
    if (widget.sendTimer.length == 0) return;
    widget.sendTimer.forEach((i) => {
          if (i["id"] == messageId) {i["timer"].cancel()}
        });
    setState(() {});
  }
}
